<script>
  export default {
    data() {
      return {
        allListData: [], // 所有的数据，比如这个数组存放了十万条数据
        itemHeight: 40, // 每一条（项）的高度，比如40像素
        count: 22, // 一屏展示几条数据
        start: 0, // 开始位置的索引
        end: 22, // 结束位置的索引
        topVal: 0, // 父元素滚动条滚动，更改子元素对应top定位的值，确保联动
        loading: false,
      };
    },
    computed: {
      // 从所有的数据allListData中截取需要展示的数据showListData
      showListData: function () {
        return this.allListData.slice(this.start, this.end);
      },
    },
    async created() {
      this.loading = true;
      for (let i = 1; i <= 200; i++){
        const obj = {
          tid:i,
          text:i
        };
        this.allListData.push(obj)
      }
      this.loading = false;
    },
    methods: {
      // 滚动这里可以加上节流，减少触发频次
      handleScroll() {
        const scrollTop = this.$refs.virtualListWrap.scrollTop;
        this.start = Math.floor(scrollTop / this.itemHeight);
        this.end = this.start + this.count;
        this.topVal = this.$refs.virtualListWrap.scrollTop + "px";
      },
    },
  };
</script>

<template>
  <!-- 虚拟列表容器，类似“窗口”，窗口的高度取决于一次展示几条数据
            比如窗口只能看到10条数据，一条40像素，10条400像素
            故，窗口的高度为400像素，注意要开定位和滚动条 -->
  <div class="virtualListWrap" ref="virtualListWrap" @scroll="handleScroll" :style="{ height: itemHeight * count + 'px' }">
    <!-- 占位dom元素，其高度为所有的数据的总高度 -->
    <div class="placeholderDom" :style="{ height: allListData.length * itemHeight + 'px' }"></div>
    <!-- 内容区，展示10条数据，注意其定位的top值是变化的 -->
    <div class="contentList" :style="{ top: topVal }">
      <!-- 每一条（项）数据 -->
      <div v-for="(item, index) in showListData" :key="index" class="itemClass" :style="{ height: itemHeight + 'px' }">
        {{ item.text}}
      </div>
    </div>
    <!-- 加载中部分 -->
    <div class="loadingBox" v-show="loading">
      <i class="el-icon-loading"></i>
      &nbsp;&nbsp;<span>loading...</span>
    </div>
  </div>
</template>
<style scoped>
  .itemClass{
    height: 40px;
    line-height: 40px;
  }
  .itemClass:nth-child(2n){
    background: rgba(98,107,181,.15);
  }
</style>
